using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Web;
using System.Web.UI;
using System.Collections;
using System.Data;
using System.Data.Common;
using Water.Properties;

namespace Water.Web
{
    public class AjaxReflection
    {
        public static MethodInfo MethodInfo(object target, string methodName)
        {
            Type type = target.GetType();
            try
            {
                MethodInfo methodInfo = type.GetMethod(methodName);
                if (methodInfo != null)
                {
                    object[] methodAttributes = methodInfo.GetCustomAttributes(typeof(AjaxMethodAttribute), true);
                    if (methodAttributes.Length > 0)
                    {
                        AjaxMethodAttribute methodAttribute = (AjaxMethodAttribute)(methodAttributes[0]);
                        return methodInfo;
                    }
                    else
                        throw new Exception(string.Format(Water.Resources.Globalize.ExceptionResource.ExceptionNotAjaxMethod, methodName));
                }
                else
                    throw new Exception(string.Format(Water.Resources.Globalize.ExceptionResource.ExceptionNotFoundedMethod, methodName));
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }

        }


        public static string InvokeMethod(object target, MethodInfo methodInfo, object[] parameters, ReturnType returnType)
        {
            object return_value = null;
            string ret;
            try
            {
                return_value = methodInfo.Invoke(target, parameters);
                Type return_type = methodInfo.ReturnType;
                switch (returnType)
                {
                    case ReturnType.OnlyValue:
                        if (return_type.IsPrimitive || return_type.IsValueType || return_type.IsEnum || return_value is decimal || return_value is string)
                            ret= Water.Util.Convert.ToStringFromPrimitive(return_value);
                        else
                            throw new Exception(string.Format(Water.Resources.Globalize.ExceptionResource.ExceptionReturnTypeConvert));
                        break;
                    case ReturnType.Array:
                        if((return_value is IEnumerable) && !(return_value is string))
                            ret = Water.Util.Convert.ToArrayStringFromEnumerable((IEnumerable)return_value);
                        else
                            throw new Exception(string.Format(Water.Resources.Globalize.ExceptionResource.ExceptionReturnTypeConvert));
                        break;
                    case ReturnType.JSON:
                        if(return_value is IDictionary)
                            ret = Water.Util.Convert.ToJSONStringFromDictionary((IDictionary)return_value);
                        else if(return_type.IsClass || return_value is object)
                            ret = Water.Util.Convert.ToJSONStringFromCustomObect(return_value);
                        else
                            throw new Exception(string.Format(Water.Resources.Globalize.ExceptionResource.ExceptionReturnTypeConvert));
                        break;
                    case ReturnType.JSONInArray:
                        if (return_type.IsGenericType)
                        {
                            Type gt = return_type.GetGenericTypeDefinition();
                            if ((typeof(IList<>).IsAssignableFrom(gt) || typeof(List<>).IsAssignableFrom(gt)))
                               ret = Water.Util.Convert.ToArrayJSONStringFromGenercList(return_value);
                            else
                               throw new Exception(string.Format(Water.Resources.Globalize.ExceptionResource.ExceptionReturnTypeConvert));
                        }
                        else if (return_value is DataSet)
                            ret = Water.Util.Convert.ToJSONStringFromDataSet((DataSet)return_value);
                        else if (return_value is IDataReader)
                            ret = Water.Util.Convert.ToJSONStringFromDataReader((IDataReader)return_value);
                        else if (return_value is DataTable)
                            ret = Water.Util.Convert.ToJSONStringFromDataTable((DataTable)return_value);
                        else
                            throw new Exception(string.Format(Water.Resources.Globalize.ExceptionResource.ExceptionReturnTypeConvert));
                        break;
                    case ReturnType.ArrayInArray:
                        if(return_value is DataSet)
                            ret = Water.Util.Convert.ToArrayStringFromDataSet((DataSet)return_value);
                        else if(return_value is IDataReader)
                            ret = Water.Util.Convert.ToArrayStringFromDataReader((IDataReader)return_value);
                        else if(return_value is DataTable)
                            ret = Water.Util.Convert.ToArrayStringFromDataTable((DataTable)return_value);
                        else
                            throw new Exception(string.Format(Water.Resources.Globalize.ExceptionResource.ExceptionReturnTypeConvert));
                        break;
                    default:
                        throw new Exception(string.Format(Water.Resources.Globalize.ExceptionResource.ExceptionReturnTypeConvert));
                        //break;
                }
            }
            catch (TargetInvocationException e)
            {
                if (e.InnerException != null)
                    throw e.InnerException;
                else
                    throw e;
            }
            return ret;
        }
    }
}
